package com.gobang.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gobang.common.exception.ErrorCode;
import com.gobang.common.exception.ScoreException;
import com.gobang.common.util.ScoreUtils;
import com.gobang.domain.dto.ScoreUpdateRequestDTO;
import com.gobang.domain.entity.ScoreRecord;
import com.gobang.domain.vo.ScoreRecordQueryVO;
import com.gobang.domain.vo.ScoreRecordVO;
import com.gobang.domain.vo.ScoreUpdateResponseVO;
import com.gobang.domain.vo.UserInfoVO;
import com.gobang.mapper.ScoreRecordMapper;
import com.gobang.service.ScoreService;
import com.gobang.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 积分管理业务服务实现类
 * 
 * @author System
 * @since 1.0.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ScoreServiceImpl implements ScoreService {

    private final ScoreRecordMapper scoreRecordMapper;
    private final UserService userService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ScoreUpdateResponseVO updateUserScore(ScoreUpdateRequestDTO request) {
        log.info("开始更新用户积分: userId={}, gameResult={}", request.getUserId(), request.getGameResult());

        // 1. 验证用户是否存在
        UserInfoVO user = userService.getUserById(request.getUserId());
        if (user == null) {
            log.error("用户积分更新失败，用户不存在: userId={}", request.getUserId());
            throw new ScoreException(ErrorCode.USER_NOT_FOUND);
        }

        UserInfoVO opponent = userService.getUserById(request.getOpponentId());
        if (opponent == null) {
            log.error("用户积分更新失败，对手用户不存在: opponentId={}", request.getOpponentId());
            throw new ScoreException(ErrorCode.USER_NOT_FOUND, "对手用户不存在");
        }

        // 2. 计算积分变化：WIN LOSE-> +5 -3
        int scoreChange = ScoreUtils.calculateScoreChange(request.getGameResult());
        log.debug("积分变化计算完成: userId={}, gameResult={}, scoreChange={}", 
                 request.getUserId(), request.getGameResult(), scoreChange);

        // 3. 计算新积分: CurrentScore + (+5/-3) -> newScore(不能<0)
        int newScore = ScoreUtils.validateNewScore(user.getCurrentScore(), scoreChange);
        log.debug("新积分计算完成: userId={}, currentScore={}, newScore={}", 
                 request.getUserId(), user.getCurrentScore(), newScore);

        // 4. 更新用户积分和游戏统计（调用用户管理模块的方法）
        boolean isWin = "WIN".equals(request.getGameResult());
        boolean updateSuccess = userService.updateUserGameStats(request.getUserId(), scoreChange, isWin);

        if (!updateSuccess) {
            log.error("用户积分更新失败，数据库更新失败: userId={}", request.getUserId());
            throw new ScoreException(ErrorCode.SCORE_UPDATE_FAILED);
        }

        // 5. 创建积分记录
        ScoreRecord record = new ScoreRecord();
        record.setUserId(request.getUserId());
        record.setOpponentId(request.getOpponentId());
        record.setRoomId(request.getRoomId());
        record.setGameResult(isWin ? 1 : 0);
        record.setScoreChange(scoreChange);
        record.setGameTime(LocalDateTime.now());

        int insertResult = scoreRecordMapper.insert(record);
        if (insertResult == 0) {
            log.error("积分记录创建失败: userId={}", request.getUserId());
            throw new ScoreException(ErrorCode.SCORE_RECORD_CREATE_FAILED);
        }

        log.debug("积分记录创建成功: recordId={}, userId={}", record.getId(), request.getUserId());

        // 6. 构建响应结果（重新获取用户信息以确保数据准确性）
        UserInfoVO updatedUser = userService.getUserById(request.getUserId());
        ScoreUpdateResponseVO response = new ScoreUpdateResponseVO();
        response.setSuccess(true);
        response.setNewScore(updatedUser.getCurrentScore());
        response.setTotalGames(updatedUser.getTotalGames());
        response.setWinGames(updatedUser.getWinGames());
        response.setWinRate(updatedUser.getWinRate());

        log.info("用户积分更新成功: userId={}, newScore={}, totalGames={}, winGames={}", 
                request.getUserId(), response.getNewScore(), response.getTotalGames(), response.getWinGames());

        return response;
    }

    @Override
    public ScoreRecordQueryVO getScoreRecordsByUserId(Long userId, Integer current, Integer size) {
        log.debug("查询用户积分流水记录: userId={}, current={}, size={}", userId, current, size);

        // 1. 验证用户是否存在
        UserInfoVO user = userService.getUserById(userId);
        if (user == null) {
            log.error("用户积分流水查询失败，用户不存在: userId={}", userId);
            throw new ScoreException(ErrorCode.USER_NOT_FOUND);
        }

        // 2. 构建分页参数
        Page<ScoreRecord> page = new Page<>(current, size);

        // 3. 查询积分记录（使用简单查询，不使用JOIN）
        LambdaQueryWrapper<ScoreRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ScoreRecord::getUserId, userId)
                    .orderByDesc(ScoreRecord::getGameTime);
        
        IPage<ScoreRecord> recordPage = scoreRecordMapper.selectPage(page, queryWrapper);

        log.debug("积分流水记录查询完成: userId={}, total={}, pages={}", 
                 userId, recordPage.getTotal(), recordPage.getPages());

        // 4. 组装返回数据
        ScoreRecordQueryVO result = new ScoreRecordQueryVO();
        result.setCurrent(current);
        result.setSize(size);
        result.setTotal(recordPage.getTotal());
        result.setPages((int) recordPage.getPages());

        // 5. 转换记录数据
        List<ScoreRecordVO> records = recordPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        result.setRecords(records);

        log.debug("用户积分流水记录查询成功: userId={}, recordCount={}", userId, records.size());

        return result;
    }

    /**
     * 转换积分记录为VO对象
     */
    private ScoreRecordVO convertToVO(ScoreRecord record) {
        ScoreRecordVO vo = new ScoreRecordVO();
        vo.setId(record.getId());
        vo.setOpponentId(record.getOpponentId());
        vo.setGameResult(record.getGameResult() == 1 ? "WIN" : "LOSE");
        vo.setScoreChange(record.getScoreChange());
        vo.setGameTime(record.getGameTime());
        vo.setCreatedAt(record.getCreatedAt());
        vo.setRoomId(record.getRoomId());

        // 获取对手用户名
        try {
            UserInfoVO opponent = userService.getUserById(record.getOpponentId());
            if (opponent != null) {
                vo.setOpponentUsername(opponent.getUsername());
            } else {
                vo.setOpponentUsername("未知用户");
                log.warn("对手用户信息不存在: opponentId={}", record.getOpponentId());
            }
        } catch (Exception e) {
            vo.setOpponentUsername("未知用户");
            log.warn("获取对手用户信息失败: opponentId={}, error={}", record.getOpponentId(), e.getMessage());
        }

        return vo;
    }
} 